package com.tlgen.orm.utils.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 高性能对象操作工具类
 * 支持多级继承、缓存字段访问提高性能
 */
public class ObjectUtils {

    // 缓存类字段结构 (类 -> 字段映射)
    private static final Map<Class<?>, Map<String, Field>> FIELD_CACHE = new ConcurrentHashMap<>();

    // 基本类型兼容映射
    private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_MAP = new HashMap<>(16);

    static {
        PRIMITIVE_WRAPPER_MAP.put(boolean.class, Boolean.class);
        PRIMITIVE_WRAPPER_MAP.put(byte.class, Byte.class);
        PRIMITIVE_WRAPPER_MAP.put(char.class, Character.class);
        PRIMITIVE_WRAPPER_MAP.put(double.class, Double.class);
        PRIMITIVE_WRAPPER_MAP.put(float.class, Float.class);
        PRIMITIVE_WRAPPER_MAP.put(int.class, Integer.class);
        PRIMITIVE_WRAPPER_MAP.put(long.class, Long.class);
        PRIMITIVE_WRAPPER_MAP.put(short.class, Short.class);
        PRIMITIVE_WRAPPER_MAP.put(void.class, Void.class);
    }

    /**
     * 安全地将源对象的字段复制到目标对象
     *
     * @param source 源对象
     * @param target 目标对象（已实例化的对象）
     */
    public static void fastCopy(Object source, Object target) {
        if (source == null || target == null) return;

        try {
            // 获取所有字段映射
            Map<String, Field> sourceFields = getAllFields(source.getClass());
            Map<String, Field> targetFields = getAllFields(target.getClass());

            // 遍历源字段（按来源类分组）
            for (Map.Entry<String, Field> sourceEntry : sourceFields.entrySet()) {
                // 解析复合键中的类名和字段名
                String[] parts = sourceEntry.getKey().split(":");
                String className = parts[0];
                String fieldName = parts[1];

                // 查找目标中同源的字段
                String targetKey = className + ":" + fieldName;
                if (!targetFields.containsKey(targetKey)) continue;

                Field sourceField = sourceEntry.getValue();
                Field targetField = targetFields.get(targetKey);

                if (isCompatibleType(sourceField, targetField)) {
                    copyFieldValue(source, target, sourceField, targetField);
                }
            }
        } catch (Exception e) {
            // 在实际项目中应使用日志框架记录异常
            e.printStackTrace();
        }
    }

    /**
     * 创建新对象并复制字段
     *
     * @param source      源对象
     * @param targetClass 目标类
     * @return 新创建的复制对象
     */
    public static <T> T fastCopyAndNew(Object source, Class<T> targetClass) {
        if (source == null || targetClass == null) return null;

        try {
            // 创建目标对象实例
            T target = targetClass.getDeclaredConstructor().newInstance();

            // 执行复制
            fastCopy(source, target);

            return target;
        } catch (Exception e) {
            // 在实际项目中应使用日志框架记录异常
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 创建新对象列表并复制字段
     *
     * @param sourceList  源对象列表
     * @param targetClass 目标类
     * @return 新创建的复制对象列表
     */
    public static <T> List<T> fastCopyAndNewList(List<?> sourceList, Class<T> targetClass) {
        if (sourceList == null || sourceList.isEmpty()) return Collections.emptyList();

        return sourceList.stream()
                .map(source -> fastCopyAndNew(source, targetClass))
                .collect(Collectors.toList());
    }

    // ============== 内部工具方法 ============== //

    /**
     * 获取类及其所有父类的字段映射（包含缓存）
     */
    private static Map<String, Field> getAllFields(Class<?> clazz) {
        return FIELD_CACHE.computeIfAbsent(clazz, ObjectUtils::resolveAllFields);
    }

    /**
     * 解析类及其所有父类的字段（直到Object类）
     */
    private static Map<String, Field> resolveAllFields(Class<?> clazz) {
        // 使用特殊键名格式区分不同类的字段
        Map<String, Field> fieldMap = new LinkedHashMap<>();
        Class<?> currentClass = clazz;

        // 遍历类层次结构
        while (currentClass != null && currentClass != Object.class) {
            for (Field field : currentClass.getDeclaredFields()) {
                if (Modifier.isStatic(field.getModifiers())) continue;

                field.setAccessible(true);

                // 创建包含类名的复合键
                String compositeKey = currentClass.getName() + ":" + field.getName();
                fieldMap.put(compositeKey, field);
            }
            currentClass = currentClass.getSuperclass();
        }
        return Collections.unmodifiableMap(fieldMap);
    }

    /**
     * 检查字段类型是否兼容
     */
    private static boolean isCompatibleType(Field sourceField, Field targetField) {
        Class<?> sourceType = sourceField.getType();
        Class<?> targetType = targetField.getType();

        // 1. 相同类型直接兼容
        if (sourceType == targetType) return true;

        // 2. 基本类型和包装类型的兼容检查
        if (isPrimitiveAndWrapperCompatible(sourceType, targetType)) return true;

        // 3. 检查继承关系
        return targetType.isAssignableFrom(sourceType);
    }

    /**
     * 检查基本类型和包装类型的兼容性
     */
    private static boolean isPrimitiveAndWrapperCompatible(Class<?> type1, Class<?> type2) {
        // 处理基本类型和包装类型的兼容
        return PRIMITIVE_WRAPPER_MAP.get(type1) == type2 ||
                PRIMITIVE_WRAPPER_MAP.get(type2) == type1 ||
                PRIMITIVE_WRAPPER_MAP.get(type1) == PRIMITIVE_WRAPPER_MAP.getOrDefault(type2, type2);
    }

    /**
     * 复制字段值
     */
    private static void copyFieldValue(Object source, Object target,
                                       Field sourceField, Field targetField) {
        try {
            Object value = sourceField.get(source);
            if (value != null) {
                targetField.set(target, value);
            }
        } catch (IllegalAccessException e) {
            // 在实际项目中应使用日志框架记录异常
            e.printStackTrace();
        }
    }

}